#ifndef __M_BUFFER_H__
#define __M_BUFFER_H__

#include "util.hpp"
#include <iostream>
#include <vector>
#include <cassert>
namespace mylog{

  #define DEFAULT_BUFFER_SIZE (10 * 1024 * 1024)  //10M
  #define THRESHOLD_BUFFER_SIZE (80 * 1024 * 1024) //80M
  #define INCREMENT_BUFFER_SIZE (1 * 1024 * 1024)  //1M
  class Buffer{
    public:
      Buffer():_buffer(DEFAULT_BUFFER_SIZE),_writer_idx(0),_reader_idx(0) {}
      //向缓冲区中写入数据
      void push(const char* data, size_t len){
        //如果空间不够，动态扩容
        ensureEnoughSize(len);
        //直接调用copy拷贝
        std::copy(data, data + len, &_buffer[_writer_idx]);
        //将当前写入位置向后偏移
        moveWriter(len);
      }
      //返回可读数据的起始地址
      const char* begin(){
        return &_buffer[_reader_idx];
      }
      //返回可写数据的长度
      size_t writeAbleSize(){
        return (_buffer.size() - _writer_idx);
      }
      //返回可读数据的长度
      size_t readAbleSize(){
        return (_writer_idx - _reader_idx);
      }
      void moveReader(size_t len){
        assert(len <= readAbleSize());
        _reader_idx += len;
      }
      //重置读写位置，初始化缓冲区
      void reset(){
        _writer_idx = 0;  
        _reader_idx = 0;
      }
      //对buffer进行交换
      void swap(Buffer& buffer){
        _buffer.swap(buffer._buffer);
        std::swap(_reader_idx, buffer._reader_idx);
        std::swap(_writer_idx, buffer._writer_idx);
      }
      //判断缓冲区是否为空
      bool empty(){
        return (_writer_idx == _reader_idx);
      }
    private:
      void ensureEnoughSize(size_t len){
          if(len < writeAbleSize())  return;  //不需要扩容
          size_t new_size = 0;
          if(_buffer.size() < THRESHOLD_BUFFER_SIZE){
               new_size = _buffer.size() * 2 + len;
          }else{
               new_size = _buffer.size() + INCREMENT_BUFFER_SIZE + len; //线性增长
          }
          _buffer.resize(new_size);
      }
      void moveWriter(size_t len){
        assert(len <= _buffer.size());
        _writer_idx += len;
      }
    private:
      std::vector <char> _buffer;
      size_t _writer_idx;  //当前可写数据的下标
      size_t _reader_idx;  //当前可读数据的下标
  };

}



#endif
